﻿using CSRedis;
using furion.blog.Application.Contracts;
using furion.blog.Domain.IRepositories;
using furion.blog.Domain.MySQL;
using furion.blog.Domain.Query.Member;
using furion.blog.Domain.Shared;
using furion.blog.Domain.Shared.Dto.Member;
using furion.blog.Domain.Shared.Dto.Wx.MiniProgram;
using furion.blog.Domain.Shared.Enum;
using furion.blog.Domain.Shared.Vo.Member;
using furion.blog.Domain.Shared.Vo.Shop;
using furion.blog.Utils;
using Furion;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace furion.blog.Application
{
    public class MemberService : IMemberService, ISingleton
    {
        private readonly IWxService _wxService;
        private readonly IMemberRepository _memberRepository;
        private readonly CSRedisClient[] _csredis;

        public MemberService(IWxService wxService, 
            IMemberRepository memberRepository,
            CSRedisClient[] csredis
            )
        {
            this._wxService = wxService;
            this._memberRepository = memberRepository;
            this._csredis = csredis;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<MemberLoginSuccessVO> Login(MemberLoginDto dto)
        {
            if (dto.Type.ToUpper() == MemberLoginTypeEnum.Code.ToString().ToUpper())
            {
                return await LoginByCode(dto);
            }
            return null;
        }

        /// <summary>
        /// 通过code登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        private async Task<MemberLoginSuccessVO> LoginByCode(MemberLoginDto dto)
        {
            Code2SessionDto codeDto = await this._wxService.Code2Session(dto.Code);
            if (!string.IsNullOrWhiteSpace(codeDto.SessionKey) && !string.IsNullOrWhiteSpace(codeDto.OpenId))
            {
                //获取成功
                DateTime now = DateTime.Now;
                Member member = await this._memberRepository.First(new MemberDetailQuery { MiniProgramOpenId = codeDto.OpenId }.Exp());
                if (member == null)
                {
                    //不存在，进行自动注册
                    member = new Member
                    {
                        MemberId = IdUtil.Id(),
                        Phone = string.Empty,
                        Password = string.Empty,
                        RealName = string.Empty,
                        NickName = IdUtil.ShortId(),
                        Sex = SexEnum.Unknow.ToString(),
                        Birthday = null,
                        Integral = Decimal.Zero,
                        Balance = Decimal.Zero,
                        Email = string.Empty,
                        Avatar = App.Configuration["Member:DefaultHead"],
                        MiniProgramOpenid = codeDto.OpenId,
                        WechatOpenid = string.Empty,
                        CreatedTime = now,
                        UpdatedTime = now,
                        Status = StatusEnum.Normal.ToString(),
                        IsDelete = YesOrNoEnum.No.ToString(),
                        Location = string.Empty,
                        Wechat = String.Empty,
                    };
                    bool ret = await this._memberRepository.Save(member);
                    if (!ret)
                    {
                        throw Oops.Oh("会员信息保存失败");
                    }
                }
                //返回给前端
                var claims = new Dictionary<string, object> {
                //隐藏信息
                { "id",member.MemberId},{ "role","Member"}
                };
                var token = JwtUtil.CreateToken(claims);
                return new MemberLoginSuccessVO { Token = token, Avatar = member.Avatar, NickName = member.NickName };
            }
            else
            {
                //获取失败
                throw Oops.Oh("通过code获取信息失败");
            }
        }


        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public async Task<PageVO> List(MemberListQuery query)
        {
            return await this._memberRepository.List(query);
        }


        /// <summary>
        /// 更新位置信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task UpdateLocation(MemberLocationDto dto)
        {
            //更新数据库的location字段
            Member member = await this._memberRepository.First(new MemberDetailQuery { MemberId = dto.MemberId }.Exp());
            if (member == null)
            {
                throw Oops.Oh("会员信息不存在");
            }
            var obj = new { lat = dto.Lat, lng = dto.Lng, addr = dto.Addr, city = dto.City , memberId = dto.MemberId};
            await this._memberRepository.UpdateLocation(dto.MemberId, JSON.Serialize(obj));
            //更新redis里面的位置信息
            await this._csredis[14].GeoAddAsync("member_location",latitude:dto.Lat,longitude:dto.Lng,member:obj);
        }


        /// <summary>
        /// 更新个人信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task UpdateProfile(MemberProfileUpdateDto dto) {
            Member member = await this._memberRepository.FindById(dto.MemberId);
            if (member == null) {
                throw Oops.Oh("信息不存在");
            }
            await this._memberRepository.UpdateProfile(dto);
        }


        /// <summary>
        /// 会员资料
        /// </summary>
        /// <param name="memberId"></param>
        /// <returns></returns>
        public async Task<MemberProfileVO> Profile(long memberId) {
            Member member = await this._memberRepository.FindById(memberId);
            if (member == null) {
                throw Oops.Oh("信息不存在");
            }
            return member.Adapt<MemberProfileVO>();
        }


        /// <summary>
        /// 绑定手机号码
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<bool> BindPhone(MemberPhoneBindDto dto) {
            //校验验证码
            var captcha = await this._csredis[13].GetAsync(dto.Phone);
            if (captcha == null) {
                throw Oops.Oh("验证码已失效");
            }
            if (captcha != dto.Captcha) {
                throw Oops.Oh("验证码有误");
            }
            //查找手机号码是否已经被绑定了 
            var member = await this._memberRepository.FindByPhone(dto.Phone);
            if (member != null && member.MemberId != dto.MemberId) {
                throw Oops.Oh("号码已被绑定");
            }
            return await this._memberRepository.UpdatePhone(dto.MemberId,dto.Phone);
        }

       
        /// <summary>
        /// 通过id查找实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<Member> Model(long id) {
            return await this._memberRepository.FindById(id);
        }

    }
}
